# coding=utf-8

from string import Template
from generator.libsomeip.some_ip_type import SomeIP
from utils.payload import TypeEnum

from utils.util import writeFile

write_property_cpp=Template(
"""
#include <someip.pb.h>
#include "PlatformProperty.h"

TRANSMIT_WRITE_PROPERTY(${properyName},${propType}) {
    builder
        .area(VehicleArea::GLOBAL)
        .immutableStatus(PropertyStatus::Active)
        .onSetProperty([](const ${propType}& value) {
${impl}
        });
}
"""
)

templete_base_type_parse=Template(
"""
            SIGNAL.set${signalName}(value);
"""
)

templete_enum_type_parse=Template(
"""
            SIGNAL.set${signalName}(someip::${propType}((int32_t)value));
"""
)

templete_array_parse=Template(
"""
            std::array<${propType},${len}> arr{};
            int32_t realLen = value.size() < ${len} ? value.size() : ${len};
            std::copy_n(value.begin(), realLen, arr.begin());
            SIGNAL.set${signalName}(arr);
"""
)

templete_string_parse=Template(
"""
            SIGNAL.set${signalName}(value);
"""
)

templete_struct_parse=Template(
"""
            ${struct_Type} structObj;
${members}       
            SIGNAL.set${signalName}(structObj);
"""
)

templete_struct_member_parse=Template(
"""            structObj.${member}=(${convert_type})value.${protoMember}();"""
)


def gen_SomeIPWriteDirectTransmitProperty(someip:SomeIP):
    for msg in [msg for msg in someip.msg if msg.isSend()]:
        for item in [item for item in msg.item if item.isDirectTransmit()]:
            if item.payloadType.isNormal():
                if item.encodeType is not None and item.encodeType.isEnum():
                    writeFile("../vhal_platform/directTransmit", "{}.cpp".format(item.msgName),
                        lambda file: file.write(write_property_cpp.substitute(
                            properyName=item.msgName,
                            propType=item.encodeType.getTypeName(),
                            impl=templete_enum_type_parse.substitute(
                                    signalName=item.msgName,
                                    propType=item.encodeType.getTypeName()
                                )
                        )))
                else:
                    def to_type(payload_type):
                        if payload_type.value<=6:
                            return "int32_t"
                        elif payload_type.value<=8:
                            return "int64_t"
                        else:
                            return "float"
                    writeFile("../vhal_platform/directTransmit", "{}.cpp".format(item.msgName),
                        lambda file: file.write(write_property_cpp.substitute(
                            properyName=item.msgName,
                            propType=to_type(item.payloadType),
                            impl=templete_base_type_parse.substitute(
                                    signalName=item.msgName
                                )
                        )))
            elif item.payloadType.isArray():
                def array_type(payload_type):
                    if payload_type==TypeEnum.int8_t_array or payload_type==TypeEnum.uint8_t_array:
                        return "uint8_t"
                    elif payload_type==TypeEnum.int16_t_array or payload_type==TypeEnum.uint16_t_array:
                        return "int32_t"
                    elif payload_type==TypeEnum.int32_t_array or payload_type==TypeEnum.uint32_t_array:
                        return "int32_t"
                    elif payload_type==TypeEnum.int64_t_array or payload_type==TypeEnum.uint64_t_array:
                        return "int64_t"
                    elif payload_type==TypeEnum.float_array:
                        return "float"
                writeFile("../vhal_platform/directTransmit", "{}.cpp".format(item.msgName),
                        lambda file: file.write(write_property_cpp.substitute(
                            properyName=item.msgName,
                            propType="std::vector<{}>".format(array_type(item.payloadType)),
                            impl=templete_array_parse.substitute(
                                    signalName=item.msgName,
                                    propType=array_type(item.payloadType),
                                    len=item.payloadLen
                                )
                        )))
            elif item.payloadType.isString():
                writeFile("../vhal_platform/directTransmit", "{}.cpp".format(item.msgName),
                        lambda file: file.write(write_property_cpp.substitute(
                            properyName=item.msgName,
                            propType="std::string",
                            impl=templete_string_parse.substitute(
                                    signalName=item.msgName
                                )
                        )))
            elif item.payloadType.isStruct():
                members=[]
                encodeType = item.encodeType
                for (member,desc) in encodeType.members:
                    (filedType,filedName)=member.split(" ")
                    members.append(templete_struct_member_parse.substitute(
                        member=filedName,
                        protoMember=filedName.lower(),
                        convert_type=filedType

                    ))
                writeFile("../vhal_platform/directTransmit", "{}.cpp".format(item.msgName),
                        lambda file: file.write(write_property_cpp.substitute(
                            properyName=item.msgName,
                            propType="proto::someip::"+item.encodeType.getTypeName(),
                            impl=templete_struct_parse.substitute(
                                    signalName=item.msgName,
                                    struct_Type=item.encodeType.getTypeName(),
                                    members="\n".join(members)
                                )
                        )))

    